<?php

declare(strict_types=1);

use think\facade\Db;
use think\migration\Migrator;

class SeedSystemConfigAndMenu extends Migrator
{
    public function up(): void
    {
        $this->seedConfigs();
        $this->seedMenus();
    }

    public function down(): void
    {
        Db::name('sys_config')
            ->whereIn('config_key', array_column($this->configs(), 'config_key'))
            ->delete();

        Db::name('sys_menu')
            ->whereIn('identifier', $this->collectMenuCodes($this->menus()))
            ->delete();
    }

    private function seedConfigs(): void
    {
        $now = date('Y-m-d H:i:s');
        $configs = $this->configs();

        Db::name('sys_config')
            ->whereIn('config_key', array_column($configs, 'config_key'))
            ->delete();

        foreach ($configs as $config) {
            Db::name('sys_config')->insert([
                'config_key' => $config['config_key'],
                'value_type' => $config['value_type'],
                'config_value' => $config['config_value'],
                'description' => $config['description'],
                'category' => $config['category'],
                'status' => 1,
                'create_time' => $now,
                'update_time' => $now,
            ]);
        }
    }

    private function seedMenus(): void
    {
        $menus = $this->menus();
        $identifiers = $this->collectMenuCodes($menus);

        Db::name('sys_menu')
            ->whereIn('identifier', $identifiers)
            ->delete();

        $now = date('Y-m-d H:i:s');

        $insertMenu = function (array $menu, int $parentId) use (&$insertMenu, $now): void {
            $menuId = Db::name('sys_menu')->insertGetId([
                'parent_id' => $parentId,
                'type' => $menu['type'] ?? 'menu',
                'identifier' => $menu['identifier'],
                'name' => $menu['name'],
                'path' => $menu['path'] ?? '',
                'component' => $menu['component'] ?? '',
                'redirect' => $menu['redirect'] ?? '',
                'meta' => json_encode($menu['meta'] ?? [], JSON_UNESCAPED_UNICODE),
                'permission_code' => $menu['permission_code'] ?? null,
                'client_type' => $menu['client_type'] ?? 'admin',
                'sort' => $menu['sort'] ?? 0,
                'is_visible' => $menu['is_visible'] ?? 1,
                'status' => 1,
                'create_time' => $now,
                'update_time' => $now,
            ]);

            if (!empty($menu['children'])) {
                foreach ($menu['children'] as $index => $child) {
                    $child['sort'] = $child['sort'] ?? $index;
                    $insertMenu($child, (int) $menuId);
                }
            }

            if (!empty($menu['buttons'])) {
                foreach ($menu['buttons'] as $index => $button) {
                    Db::name('sys_menu')->insert([
                        'parent_id' => $menuId,
                        'type' => 'button',
                        'identifier' => $button['identifier'],
                        'name' => $button['name'],
                        'path' => '',
                        'component' => '',
                        'redirect' => '',
                        'meta' => json_encode([
                            'title' => $button['name'],
                            'icon' => $button['icon'] ?? '',
                            'rank' => $button['rank'] ?? $index,
                            'showLink' => false,
                            'showParent' => false,
                        ], JSON_UNESCAPED_UNICODE),
                        'permission_code' => $button['permission_code'] ?? null,
                        'client_type' => $menu['client_type'] ?? 'admin',
                        'sort' => $button['sort'] ?? $index,
                        'is_visible' => 0,
                        'status' => 1,
                        'create_time' => $now,
                        'update_time' => $now,
                    ]);
                }
            }
        };

        foreach ($menus as $index => $menu) {
            $menu['sort'] = $menu['sort'] ?? $index;
            $insertMenu($menu, 0);
        }
    }

    private function configs(): array
    {
        return [
            [
                'config_key' => 'platform.name',
                'value_type' => 'string',
                'config_value' => 'Bearing Shop Platform',
                'description' => '平台名称',
                'category' => 'platform',
            ],
            [
                'config_key' => 'platform.commission.platform_rate',
                'value_type' => 'int',
                'config_value' => '5',
                'description' => '平台抽成比例(%)',
                'category' => 'commission',
            ],
            [
                'config_key' => 'platform.commission.developer_rate',
                'value_type' => 'decimal',
                'config_value' => '1',
                'description' => '开发者抽成比例(%)',
                'category' => 'commission',
            ],
            [
                'config_key' => 'platform.commission.operator_rate',
                'value_type' => 'decimal',
                'config_value' => '0.5',
                'description' => '客服抽成比例(%)',
                'category' => 'commission',
            ],
            [
                'config_key' => 'qiniu',
                'value_type' => 'json',
                'config_value' => json_encode([
                    'accessKey' => '_OpxHj4uH95C_6WrIqsElZ3Oi72J3X_oMWYfqtvF',
                    'secretKey' => 'smBbTusIbwyroF67r3r-18a2AoTVAHgeY8w7IGyf',
                    'bucket' => 'bcbiz',
                    'domain' => 'https://static.bcbiz.com',
                    'uploadUrl' => 'http://upload.qiniup.com',
                ], JSON_UNESCAPED_UNICODE),
                'description' => '七牛云存储配置',
                'category' => 'storage',
            ],
            [
                'config_key' => 'jwt',
                'value_type' => 'json',
                'config_value' => json_encode([
                    'key' => 'bH3xZ5yGNlpfHH9fvf9xgon4QnvFuR1o6bSXTC0tdV9Yf9dnN4FXzdR0fhcJUVse',
                    'algorithm' => 'HS256',
                    'access_expire' => 7200,
                    'refresh_expire' => 604800,
                ], JSON_UNESCAPED_UNICODE),
                'description' => 'JWT 配置',
                'category' => 'auth',
            ],
            [
                'config_key' => 'tencent.cloud_api',
                'value_type' => 'json',
                'config_value' => json_encode([
                    'SecretId' => 'AKIDGPNCuSnvqZ4MRJ0TltoW2TxJSO7dw43q',
                    'SecretKey' => '0vugUDl5C6nGWZSBi4GF2d1BMcjfOjy1',
                ], JSON_UNESCAPED_UNICODE),
                'description' => '腾讯云 API 凭证',
                'category' => 'third_party',
            ],
            [
                'config_key' => 'notify.retry',
                'value_type' => 'json',
                'config_value' => json_encode([
                    'max_attempts' => 10,
                    'intervals' => [60, 120, 300, 600, 1800, 3600, 7200, 21600, 43200, 86400],
                ], JSON_UNESCAPED_UNICODE),
                'description' => '通知发送重试策略',
                'category' => 'notify',
            ],
        ];
    }

    private function menus(): array
    {
        return array_merge(
            $this->adminMenus(),
            $this->supportMenus(),
            $this->sellerMenus()
        );
    }

    private function adminMenus(): array
    {
        return [
            $this->menu('admin.user', '用户与组织', '/system/user', 'Layout', null, 'ep:user', 10, '/system/user/accounts', [
                $this->menu('admin.user.accounts', '账户管理', '/system/user/accounts', 'system/user/accounts/index', 'admin.user.account.view', 'ep:user-filled', 1, '', [], [
                    $this->button('admin.user.accounts.create', '新增账户', 'admin.user.account.manage')
                ]),
                $this->menu('admin.user.roles', '角色管理', '/system/user/roles', 'system/user/roles/index', 'admin.user.role.view', 'ep:setting', 2),
                $this->menu('admin.user.permissions', '权限列表', '/system/user/permissions', 'system/user/permissions/index', 'admin.user.permission.view', 'ep:lock', 3),
                $this->menu('admin.org.center', '组织中心', '/system/user/org-list', 'system/org/index', 'admin.org.org.view', 'ep:office-building', 4),
            ]),
            $this->menu('admin.region', '区域管理', '/system/region', 'Layout', null, 'ep:map-location', 20, '/system/region/list', [
                $this->menu('admin.region.list', '区域维护', '/system/region/list', 'system/region/list/index', 'admin.region.view', 'ep:map-location', 1),
            ]),
            $this->menu('admin.product', '商品中心', '/system/product', 'Layout', null, 'ep:goods', 30, '/system/product/category', [
                $this->menu('admin.product.category', '类目管理', '/system/product/category', 'system/product/category/index', 'admin.product.category.view', 'ep:grid', 1),
                $this->menu('admin.product.brand', '品牌管理', '/system/product/brand', 'system/product/brand/index', 'admin.product.brand.view', 'ep:present', 2),
                $this->menu('admin.product.item', '商品管理', '/system/product/item', 'system/product/item/index', 'admin.product.item.view', 'ep:suitcase', 3),
            ]),
            $this->menu('admin.order', '订单与售后', '/system/order', 'Layout', null, 'ep:list', 40, '/system/order/list', [
                $this->menu('admin.order.list', '订单管理', '/system/order/list', 'system/order/list/index', 'admin.order.main.view', 'ep:collection', 1),
                // $this->menu('admin.order.pickup', '揽件任务', '/system/order/pickup', 'system/order/pickup/index', 'admin.order.pickup.view', 'ep:van', 2),
                $this->menu('admin.order.refund', '售后管理', '/system/order/refund', 'system/order/refund/index', 'admin.order.refund.view', 'ep:refresh', 3),
                $this->menu('admin.order.invoice', '发票对账', '/system/order/invoice', 'system/order/invoice/index', 'admin.order.invoice.view', 'ep:document', 4),
            ]),
            $this->menu('admin.finance', '结算与财务', '/system/finance', 'Layout', null, 'ep:money', 50, '/system/finance/commission', [
                $this->menu('admin.finance.commission', '佣金规则', '/system/finance/commission', 'system/finance/commission/index', 'admin.finance.commission.view', 'ep:discount', 1),
                $this->menu('admin.finance.settlement', '结算单', '/system/finance/settlement', 'system/finance/settlement/index', 'admin.finance.settlement.view', 'ep:ticket', 2),
                $this->menu('admin.finance.platform', '平台资金', '/system/finance/platform', 'system/finance/platform/index', 'admin.finance.platform.view', 'ep:wallet', 3),
            ]),
            $this->menu('admin.tms', '物流与揽件', '/system/logistics', 'Layout', null, 'ep:truck', 60, '/system/logistics/pickup', [
                $this->menu('admin.tms.pickup', '揽件任务', '/system/logistics/pickup', 'system/logistics/pickup/index', 'admin.tms.pickup.view', 'ep:takeaway-box', 1),
                $this->menu('admin.tms.trace', '物流轨迹', '/system/logistics/trace', 'system/logistics/trace/index', 'admin.tms.trace.view', 'ep:location', 2),
                $this->menu('admin.tms.express', '快递维护', '/system/logistics/express', 'system/logistics/express/index', 'admin.tms.express.view', 'ep:postcard', 3),
            ]),
            $this->menu('admin.notify', '通知与消息', '/system/notify', 'Layout', null, 'ep:bell', 70, '/system/notify/template', [
                $this->menu('admin.notify.template', '模板管理', '/system/notify/template', 'system/notify/template/index', 'admin.notify.template.view', 'ep:document', 1),
                $this->menu('admin.notify.record', '发送记录', '/system/notify/record', 'system/notify/record/index', 'admin.notify.record.view', 'ep:time', 2),
            ]),
            $this->menu('admin.system', '系统设置', '/system', 'Layout', null, 'ep:setting', 80, '/system/config', [
                $this->menu('admin.system.config', '配置管理', '/system/config', 'system/config/index', 'admin.system.config.view', 'ep:setting', 1),
                $this->menu('admin.system.menu', '菜单管理', '/system/menu', 'system/menu/index', 'admin.system.menu.view', 'ep:menu', 2),
                $this->menu('admin.system.log', '操作日志', '/system/log', 'system/log/index', 'admin.system.log.view', 'ep:notebook', 3),
            ]),
        ];
    }

    private function supportMenus(): array
    {
        return [
            $this->menu('support.task.center', '任务中心', '/system/support/tasks', 'system/support/tasks/index', 'admin.support.task.view', 'ep:timer', 101, '', [], [], 'support'),
            $this->menu('support.orders', '订单管理', '/system/support/orders', 'system/support/orders/index', 'admin.order.main.view', 'ep:list', 102, '', [], [], 'support'),
            $this->menu('support.invitation', '邀请管理', '/system/support/invite', 'system/support/invite/index', 'admin.support.invite.view', 'ep:share', 103, '', [], [], 'support'),
            $this->menu('support.express', '快递维护', '/system/support/express', 'system/support/express/index', 'admin.tms.express.view', 'ep:postcard', 104, '', [], [], 'support'),
        ];
    }

    private function sellerMenus(): array
    {
        return [
            $this->menu('seller.trade', '交易管理', '/seller/trade', 'Layout', null, 'ep:shopping-bag', 10, '/seller/trade/spotcheck', [
                $this->menu('seller.trade.spotcheck', '现货核实', '/seller/trade/spotcheck', 'seller/trade/spotcheck', 'seller.trade.spotcheck.view', 'ep:promotion', 1, '', [], [], 'seller'),
                $this->menu('seller.trade.future', '期货询价', '/seller/trade/futures', 'seller/trade/futures', 'seller.trade.future.view', 'ep:calendar', 2, '', [], [], 'seller'),
                $this->menu('seller.trade.order', '订单发货', '/seller/trade/order', 'seller/trade/order', 'seller.trade.order_delivery.view', 'ep:truck', 3, '', [], [], 'seller'),
            ], [], 'seller'),
            $this->menu('seller.product', '商品管理', '/seller/product', 'Layout', null, 'ep:goods', 20, '/seller/product/list', [
                $this->menu('seller.product.list', '商品列表', '/seller/product/list', 'seller/product/list', 'seller.product.list.view', 'ep:list', 1, '', [], [], 'seller'),
                $this->menu('seller.product.upload', '批量上传', '/seller/product/upload', 'seller/product/upload', 'seller.product.upload.view', 'ep:upload', 2, '', [], [], 'seller'),
            ], [], 'seller'),
            $this->menu('seller.fund', '资金管理', '/seller/fund', 'Layout', null, 'ep:money', 30, '/seller/fund/statement', [
                $this->menu('seller.fund.statement', '对账单', '/seller/fund/statement', 'seller/fund/statement', 'seller.fund.statement.view', 'ep:document', 1, '', [], [], 'seller'),
            ], [], 'seller'),
            $this->menu('seller.setting', '设置管理', '/seller/setting', 'Layout', null, 'ep:setting', 40, '/seller/setting/role', [
                $this->menu('seller.setting.role', '角色管理', '/seller/setting/role', 'seller/setting/role', 'seller.setting.role.view', 'ep:user', 1, '', [], [], 'seller'),
                $this->menu('seller.setting.staff', '员工管理', '/seller/setting/staff', 'seller/setting/staff', 'seller.setting.staff.view', 'ep:avatar', 2, '', [], [], 'seller'),
            ], [], 'seller'),
        ];
    }

    private function menu(
        string $identifier,
        string $name,
        string $path,
        string $component,
        ?string $permissionCode,
        string $icon,
        int $rank,
        string $redirect = '',
        array $children = [],
        array $buttons = [],
        string $clientType = 'admin'
    ): array {
        return [
            'identifier' => $identifier,
            'name' => $name,
            'path' => $path,
            'component' => $component,
            'redirect' => $redirect,
            'permission_code' => $permissionCode,
            'client_type' => $clientType,
            'meta' => [
                'title' => $name,
                'icon' => $icon,
                'rank' => $rank,
                'showLink' => true,
                'showParent' => true,
            ],
            'children' => $children,
            'buttons' => $buttons,
        ];
    }

    private function button(string $identifier, string $name, ?string $permissionCode): array
    {
        return [
            'identifier' => $identifier,
            'name' => $name,
            'permission_code' => $permissionCode,
        ];
    }

    private function collectMenuCodes(array $menus): array
    {
        $codes = [];
        $stack = $menus;

        while ($stack) {
            $item = array_pop($stack);
            $codes[] = $item['identifier'];

            if (!empty($item['children'])) {
                foreach ($item['children'] as $child) {
                    $stack[] = $child;
                }
            }

            if (!empty($item['buttons'])) {
                foreach ($item['buttons'] as $button) {
                    $codes[] = $button['identifier'];
                }
            }
        }

        return array_values(array_unique($codes));
    }
}
